package practica1.language;

import java.util.*;
import practica1.preferences.PreferencesListener;
import practica1.preferences.PreferencesXML;

/**
 * Clase de instancia que permite gestionar los idiomas de la aplicación
 * @author Miguel González - Ceura
 */
public class Language implements PreferencesListener {
    
    private static Language INSTANCE = null;
    private ResourceBundle idioma;
    private PreferencesXML prefs;
    private String idiomaCountry;
    private String idiomaLanguage;
    private ArrayList<LanguageListener> listeners;
    
    /**
     * Constructor privado de la clase por defecto
     */
    private Language() {
        prefs = PreferencesXML.getInstance();
        
        listeners = new ArrayList<LanguageListener>();
        
        initIdioma();
        initListeners();
    }
    
    private void initIdioma() {
        idiomaLanguage = prefs.getValue(this, "idiomaLanguage", "ES");
        idiomaCountry = prefs.getValue(this, "idiomaCountry", "es");
        
        idioma = ResourceBundle.getBundle("practica1/language/LanguageWords", 
                new Locale(idiomaLanguage, idiomaCountry));
    }
    
    private void initListeners() {
        prefs.addPreferencesListener(this);
    }

    /**
     * Devuelve la instancia de la clase
     * @return Language
     */
    public static Language getI() {
        if(INSTANCE == null) {
            INSTANCE = new Language();
        }
        
        return INSTANCE;
    }
    
    /**
     * Devuelve el nombre del lenguage genérico
     * @return String idiomaLanguage
     */
    public String getIdiomaLanguage() {
        return idiomaLanguage;
    }
    
    /**
     * Devuelve el idioma específico del país
     * @return String idiomaCountry
     */
    public String getIdiomaCountry() {
        return idiomaCountry;
    }
    
    /**
     * Permite suscribirse a los cambios en el idioma
     * @param l LanguageListener
     */
    public void addLanguageListener(LanguageListener l) {
        if(l != null) {
            listeners.add(l);
        }
    }
    
    /**
     * Permite desuscribirse a los cambios en el idioma
     * @param l LanguageListener
     */
    public void removeLanguageListener(LanguageListener l) {
        if(l != null) {
            listeners.remove(l);
        }
    }
    
    /**
     * Devuelve la palabra asociada con la clave que se recibe
     * @param Key Clave de la palabra
     * @return String Palabra del idioma actual
     */
    
    public String getP(String Key) {
        try {
            return idioma.getString(Key);
        } catch(MissingResourceException ex) {
            //Si la clave no existe la devolvemos tal cual
            return Key;
        }
    }
    
    /**
     * Devuelve la traducción de una palabra al idioma en ejecución
     * @param word Palabra en cualquier idioma
     * @return String Palabra en el idioma actual de ejecución
     */
    public String getT(String word) {
        try {
            //Comprobamos en cada uno de los dos idiomas si se encuentra la palabra
            ResourceBundle id1 = ResourceBundle.getBundle(
                    "practica1/language/LanguageWords", new Locale("ES", "es"));

            //Recorremos los valores del idioma en español
            Iterator it1 = id1.keySet().iterator();
            while (it1.hasNext()) {
                String clave = (String)it1.next();
                if(id1.getString(clave).equals(word)) {
                    return idioma.getString(clave);
                }
            }

            ResourceBundle id2 = ResourceBundle.getBundle(
                    "practica1/language/LanguageWords", new Locale("EN", "us"));

            //Recorremos los valores del idioma en inglés
            Iterator it2 = id1.keySet().iterator();
            while (it2.hasNext()) {
                String clave = (String)it2.next();
                if(id2.getString(clave).equals(word)) {
                    return idioma.getString(clave);
                }
            }
        } catch(MissingResourceException ex) {
            //Si hay algún error al obtener la clave devolvemos la palabra original
            return word;
        }
        
        //Si no se encuentra la traducción devolvemos la palabra original
        return word;
    }

    /**
     * Método que se llama cuando se quieren guardar las preferencias de la aplicación,
     * guarda el idioma actual en ejecución
     */
    @Override
    public void savePreferences() {
        prefs.setValue(this, "idiomaLanguage", idiomaLanguage);
        prefs.setValue(this, "idiomaCountry", idiomaCountry);
    }
    
    /**
     * Establece el nuevo idioma de la aplicación en ejecución
     * @param idiomaLanguage Idioma genérico
     * @param idiomaCountry Idioma específico del país
     */
    public void setIdioma(String idiomaLanguage, String idiomaCountry) {
        this.idiomaLanguage = idiomaLanguage;
        this.idiomaCountry = idiomaCountry;        
        idioma = ResourceBundle.getBundle("practica1/language/LanguageWords", 
                new Locale(idiomaLanguage, idiomaCountry));
        
        fireIdiomaChange();
    }
    
    /**
     * Notifica a todos los que escuchan que ha cambiado el idioma
     */
    private void fireIdiomaChange() {
        for(LanguageListener l : listeners) {
            l.idiomaChange(new LanguageEvent(idioma));
        }
    }

    /**
     * Devuelve el nombre del lenguaje actual de la aplicación (Español, Inglés)
     * @return 
     */
    public String getLanguage() {
        if(idiomaCountry.equals("ES")) {
            return idioma.getString("ESPANIOL");
        } else {
            return idioma.getString("INGLES");   
        }
    }
}
